package com.lib.utils;

import android.content.ContentProvider;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ServiceCompat;

import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;

/**
 * 对象复用池, 使用ConcurrentLinkedDeque + 软引用
 */
public class ObjPoolUtils {
    private static final int DEFAULT_MAX_SIZE = 10;
    private static final Map<String, ConcurrentLinkedDeque<SoftReference<Object>>> POOL_MAP = new ConcurrentHashMap<>();

    @Nullable
    @SuppressWarnings("unchecked")
    public static <T> T obtain(@NonNull Class<T> clazz) {
        String key = clazz.getName();
        ConcurrentLinkedDeque<SoftReference<Object>> deque = POOL_MAP.get(key);
        if (deque == null) return null;

        // 从尾部开始查找（LIFO：后进先出，性能更好）
        SoftReference<Object> ref;
        while ((ref = deque.pollLast()) != null) {
            Object obj = ref.get();
            if (obj != null) {
                return (T) obj;
            }
        }

        // 如果deque为空，从map中移除
        if (deque.isEmpty()) {
            POOL_MAP.remove(key);
        }

        return null;
    }

    public static <T> void release(@NonNull T obj) {
        release(obj, DEFAULT_MAX_SIZE);
    }

    public static <T> void release(@NonNull T obj, int maxSize) {
        if (obj == null) return;
        if (maxSize < 2) {
            maxSize = 2;
        }

        if (obj instanceof android.app.Activity
                || obj instanceof android.app.Fragment
                || obj instanceof androidx.fragment.app.Fragment
                || obj instanceof android.app.Service
                || obj instanceof android.content.ContentProvider
                || obj instanceof android.content.BroadcastReceiver
                || obj instanceof android.content.Context) {
            return; // 避免持有部分系統組件
        }

        String key = obj.getClass().getName();
        ConcurrentLinkedDeque<SoftReference<Object>> deque = POOL_MAP.get(key);

        if (deque == null) {
            deque = new ConcurrentLinkedDeque<>();
            POOL_MAP.put(key, deque);
        }

        if (deque.size() >= maxSize - 1) {
            deque.pollFirst(); // 移除最旧的对象
        }

        deque.offerLast(new SoftReference<>(obj));
    }

    public static void clear(@NonNull Class<?> clazz) {
        POOL_MAP.remove(clazz.getName());
    }

    public static void clearAll() {
        POOL_MAP.clear();
    }

    public static int getPoolSize(@NonNull Class<?> clazz) {
        ConcurrentLinkedDeque<SoftReference<Object>> deque = POOL_MAP.get(clazz.getName());
        return deque != null ? deque.size() : 0;
    }
}